#include "main.h"
#include "route_sync.h"

/**
 * @brief Validate if route number is within acceptable limits
 * This function checks if the provided route count is within system constraints
 * @param route_num: Number of routes to validate against system limits
 * @return uint8_t Returns 1 if route count is valid, 0 if exceeds constraints
 */
uint8_t is_route_num_valid(uint8_t route_num)
{
    //return !(route_num > 10);
    return 1;
}

/**
 * @brief Extract routing configuration from JSON configuration file
 * This comprehensive function parses the routing configuration from JSON file
 * and populates the global pppdMsg structure with route information for all interfaces
 * @return uint8_t Returns TRUE if configuration parsed successfully, FALSE on any error
 */
static uint8_t get_routeMsg(void)
{
    /* Static buffer to store JSON configuration content for parsing */
    static uint8_t CONFIG_STRING[JSON_LEN] = {0};
    
    /* JSON object pointer for configuration parsing and manipulation */
    cJSON *config;

    /* JSON object pointers for specific network interface configurations */
    cJSON *ppp0_item;
    cJSON *ppp1_item;
    cJSON *eht1_item;

    /* JSON array pointers for route IP addresses and subnet masks */
    cJSON *ip_arry;
    cJSON *mask_arry;

    /* Default IP address string for empty route configurations */
    char def_ip[] = "0.0.0.0 ";

    /* Initialize configuration buffer with null characters */
    memset(CONFIG_STRING, 0x00, JSON_LEN);

    /* Retrieve JSON configuration from file into local buffer */
    if (!getConfig(CONFIG_STRING, CONFIG_APN))
    {
        printf("getConfig failed!\n");
        return FALSE;
    }

    /* Parse JSON string into cJSON object structure for data extraction */
    config = string2Json(CONFIG_STRING);
    if (config == NULL)
    {
        return FALSE;
    }

    /* Extract default route device configuration from JSON object */
    strcpy(pppdMsg.defaultDev, (char *)cJSON_GetObjectItem(config, "default")->valuestring);

    /* Retrieve PPP interface configuration objects from main configuration */
    ppp0_item = cJSON_GetObjectItem(config, "ppp0");
    ppp1_item = cJSON_GetObjectItem(config, "ppp1");
    
    /* Validate that both PPP interface configurations exist in JSON */
    if ((ppp0_item == NULL) || (ppp0_item == NULL))
    {
        printf("get_routeMsg: ppp0_item or ppp0_item\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Retrieve Ethernet interface configuration with fallback compatibility */
    eht1_item = cJSON_GetObjectItem(config, "eth1");
    if (eht1_item == NULL)
    {
#if 0 /* eth0.2为原来伏羲网关的网口名称，现改为与mtk网关一致 */
			eht1_item = cJSON_GetObjectItem(config, "eth0.2");
			if (eht1_item == NULL)
			{
				cJSON_Delete(config);
				return FALSE;
			}
#else
        cJSON_Delete(config);
        return FALSE;
#endif
    }

    /***ppp0---------------------------------------------------*/
    /* Extract route IP array and subnet mask array for ppp0 interface */
    ip_arry = cJSON_GetObjectItem(ppp0_item, "route_ip");
    mask_arry = cJSON_GetObjectItem(ppp0_item, "route_netmask");
    
    /* Validate that both IP and mask arrays exist and are proper JSON arrays */
    if ((ip_arry->type != cJSON_Array) || (ip_arry == NULL) || (mask_arry->type != cJSON_Array) || (mask_arry == NULL))
    {
        cJSON_Delete(config);
        return FALSE;
    }
    
    /* Determine number of routes configured for ppp0 interface */
    pppdMsg.ppp0.route_cnt = (uint8_t)cJSON_GetArraySize(ip_arry);

    /* Set default route if no routes are configured for this interface */
    if (pppdMsg.ppp0.route_cnt == 0)
    {
        strcpy(pppdMsg.ppp0.ip[0], def_ip);
        strcpy(pppdMsg.ppp0.mask[0], def_ip);
    }

    /* Iterate through all routes for ppp0 interface and populate structure */
    for (uint8_t i = 0; i < pppdMsg.ppp0.route_cnt; i++)
    {
        /* Validate that current route entry exists in both IP and mask arrays */
        if ((cJSON_GetArrayItem(ip_arry, i) == NULL) || (cJSON_GetArrayItem(mask_arry, i) == NULL))
        {
            continue;
        }
        else
        {
            /* Copy route IP and mask from JSON arrays to pppdMsg structure */
            memcpy(pppdMsg.ppp0.ip[i], (char *)(cJSON_GetArrayItem(ip_arry, i)->valuestring), ROUTE_IP_LEN);
            memcpy(pppdMsg.ppp0.mask[i], (char *)(cJSON_GetArrayItem(mask_arry, i)->valuestring), ROUTE_IP_LEN);
        }
    }

    /***ppp1---------------------------------------------------*/
    /* Extract route IP array and subnet mask array for ppp1 interface */
    ip_arry = cJSON_GetObjectItem(ppp1_item, "route_ip");
    mask_arry = cJSON_GetObjectItem(ppp1_item, "route_netmask");
    
    /* Validate that both IP and mask arrays exist and are proper JSON arrays */
    if ((ip_arry->type != cJSON_Array) || (ip_arry == NULL) || (mask_arry->type != cJSON_Array) || (mask_arry == NULL))
    {
        cJSON_Delete(config);
        return FALSE;
    }
    
    /* Determine number of routes configured for ppp1 interface */
    pppdMsg.ppp1.route_cnt = (uint8_t)cJSON_GetArraySize(ip_arry);

    /* Set default route if no routes are configured for this interface */
    if (pppdMsg.ppp1.route_cnt == 0)
    {
        strcpy(pppdMsg.ppp1.ip[0], def_ip);
        strcpy(pppdMsg.ppp1.mask[0], def_ip);
    }

    /* Iterate through all routes for ppp1 interface and populate structure */
    for (uint8_t i = 0; i < pppdMsg.ppp1.route_cnt; i++)
    {
        /* Validate that current route entry exists in both IP and mask arrays */
        if ((cJSON_GetArrayItem(ip_arry, i) == NULL) || (cJSON_GetArrayItem(mask_arry, i) == NULL))
        {
            continue;
        }
        else
        {
            /* Copy route IP and mask from JSON arrays to pppdMsg structure */
            memcpy(pppdMsg.ppp1.ip[i], (char *)(cJSON_GetArrayItem(ip_arry, i)->valuestring), ROUTE_IP_LEN);
            memcpy(pppdMsg.ppp1.mask[i], (char *)(cJSON_GetArrayItem(mask_arry, i)->valuestring), ROUTE_IP_LEN);
        }
    }

    /***eth1--------------------------------------------------*/
    /* Extract route IP array and subnet mask array for eth1 interface */
    ip_arry = cJSON_GetObjectItem(eht1_item, "route_ip");
    mask_arry = cJSON_GetObjectItem(eht1_item, "route_netmask");
    
    /* Validate that both IP and mask arrays exist and are proper JSON arrays */
    if ((ip_arry->type != cJSON_Array) || (ip_arry == NULL) || (mask_arry->type != cJSON_Array) || (mask_arry == NULL))
    {
        cJSON_Delete(config);
        return FALSE;
    }
    
    /* Determine number of routes configured for eth1 interface */
    pppdMsg.eth1.route_cnt = (uint8_t)cJSON_GetArraySize(ip_arry);

    /* Set default route if no routes are configured for this interface */
    if (pppdMsg.eth1.route_cnt == 0)
    {
        strcpy(pppdMsg.eth1.ip[0], def_ip);
        strcpy(pppdMsg.eth1.mask[0], def_ip);
    }

    /* Iterate through all routes for eth1 interface and populate structure */
    for (uint8_t i = 0; i < pppdMsg.eth1.route_cnt; i++)
    {
        /* Validate that current route entry exists in both IP and mask arrays */
        if ((cJSON_GetArrayItem(ip_arry, i) == NULL) || (cJSON_GetArrayItem(mask_arry, i) == NULL))
        {
            continue;
        }
        else
        {
            /* Copy route IP and mask from JSON arrays to pppdMsg structure */
            memcpy(pppdMsg.eth1.ip[i], (char *)(cJSON_GetArrayItem(ip_arry, i)->valuestring), ROUTE_IP_LEN);
            memcpy(pppdMsg.eth1.mask[i], (char *)(cJSON_GetArrayItem(mask_arry, i)->valuestring), ROUTE_IP_LEN);
        }
    }

    /* Clean up JSON object to prevent memory leaks */
    cJSON_Delete(config);
    return TRUE;
}

/**
 * @brief Display routing table information for specified network device
 * This function synchronizes system routing table and displays formatted output
 * for the specified network interface including all configured routes
 * @param dev: Network device name to display routing information for
 * @return uint8_t Returns TRUE if display operation completed successfully
 */
uint8_t wwan_route_show(char *dev)
{
    /* Initialize routing table structure with zero values */
    RouteTable table = {0};
    
    /* Synchronize system routing table with application structure */
    wwan_route_sync(&table);

    /* Display formatted routing table for specified device */
    print_route_table(&table, dev);

    return TRUE;
}

/**
 * @brief Save routing table structure to persistent configuration file
 * This function processes the complete routing table and saves all device routes
 * to the JSON configuration file for persistent storage across system reboots
 * @param table: Pointer to routing table structure containing all route information
 * @return int Returns TRUE if all routes saved successfully, FALSE on any error
 */
int  save_route_table_to_file(RouteTable *table) {
    
    /* Iterate through all devices in the routing table structure */
    for (int i = 0; i < table->device_count; i++) {
        Device *device = &table->devices[i];
        
        /* Clear existing routes for this device before saving new configuration */
        clear_routeMsg(device);
        
        /* Iterate through all routes associated with current device */
        for (int j = 0; j < device->route_count; j++) {
            Route *route = &device->routes[j];
            
            /* Save individual route to configuration file with error checking */
            if (!save_routeMsg(device->device, route->destination, route->mask)) {
                return FALSE;
            }
        }
    }
    return TRUE;
}

/**
 * @brief Execute shell command and capture both exit status and error output
 * This enhanced command execution function uses fork and pipe to capture
 * command stderr output along with exit status for comprehensive error handling
 * @param cmd: Shell command string to be executed in system environment
 * @return struct cmd_result Returns structure containing exit status and error output
 */
struct cmd_result exec_cmd(const char *cmd) {
    /* File descriptors for inter-process communication pipe */
    int pipefd[2];
    
    /* Process ID for child process management */
    pid_t pid;
    
    /* Process exit status variable */
    int status;
    
    /* Buffer for reading command error output */
    char buffer[1024];
    
    /* Result structure to return command execution outcomes */
    struct cmd_result result = {0, NULL}; // Initialize result structure

    // Create pipe for inter-process communication
    if (pipe(pipefd) == -1) {
        perror("pipe");
        result.status = -1;
        return result;
    }

    // Create child process for command execution
    pid = fork();
    if (pid == -1) {
        perror("fork");
        result.status = -1;
        close(pipefd[0]);
        close(pipefd[1]);
        return result;
    }

    if (pid == 0) { // Child process
        close(pipefd[0]); // Close pipe read end in child process
        dup2(pipefd[1], STDERR_FILENO); // Redirect stderr to pipe write end
        close(pipefd[1]); // Close original pipe write end

        // Execute command using shell interpreter
        execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);

        // If execl() returns, command execution failed
        perror("execl");
        exit(1); 
    } else { // Parent process
        close(pipefd[1]); // Close pipe write end in parent process
        ssize_t bytes_read;
        size_t error_output_size = 0;
        result.error_output = NULL;

        // Read command error output from pipe until end of stream
        while ((bytes_read = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
            // Dynamically allocate memory to store accumulated error output
            result.error_output = realloc(result.error_output, error_output_size + bytes_read + 1);
            if (!result.error_output) {
                perror("realloc failed");
                result.status = -1;
                break;
            }
            // Append current buffer content to accumulated error output
            memcpy(result.error_output + error_output_size, buffer, bytes_read);
            error_output_size += bytes_read;
        }

        // Null-terminate the accumulated error output string
        if (result.error_output) {
            result.error_output[error_output_size] = '\0';
        }

        // Wait for child process to complete execution
        waitpid(pid, &status, 0);

        // Extract command exit status from child process
        if (WIFEXITED(status)) {
            result.status = WEXITSTATUS(status);
        } else {
            result.status = -1; // Child process terminated abnormally
        }
    }

    return result;
}

/**
 * @brief Configure specified network device as default route in system
 * This function updates both system routing table and configuration file
 * to set the specified network interface as the default gateway
 * @param dev: Network device name to configure as default route
 * @return uint8_t Returns TRUE if default route configuration successful
 */
uint8_t wwan_route_defaultSet(char *dev)
{
    /* Static buffer for JSON configuration content */
    static uint8_t CONFIG_STRING[JSON_LEN] = {0};
    
    /* JSON object pointer for configuration manipulation */
    cJSON *config = NULL;
    
    /* JSON object pointer for default route configuration */
    cJSON *default_route = NULL;
    
    /* String buffer for formatted JSON configuration output */
    char *CONFIG_WRITE = NULL;
    
    /* Function return status variable */
    uint8_t ret = FALSE;
    
    /* Buffer for system command execution */
    char cmd[256] = {0};
    
    /* Structure to capture command execution results */
    struct cmd_result r;

    /* Initialize configuration buffer with null characters */
    memset(CONFIG_STRING, 0x00, JSON_LEN);

    /* Retrieve current configuration from JSON file */
    if (!getConfig(CONFIG_STRING, CONFIG_APN))
    {
        printf("ERROR: wwan_route_defaultSet error!\n");
        return FALSE;
    }

    /* Parse JSON configuration string into cJSON object structure */
    config = string2Json(CONFIG_STRING);
    
    /* Validate input parameter is not NULL */
    if (dev == NULL)
    {
        printf("ERROR: wwan_route_defaultSet error!\n");
        return FALSE;
    }

    /* Verify that specified device type is supported by system */
    if (!is_dev_type_valid(dev))
    {
        printf("ERROR: wwan_route_defaultSet error!\n");
        goto ERROR_POINT;
    }

    // Set specified device as default route in system routing table
    if ( 0 != set_default_route(dev)){

        printf("ERROR: set_default_route error!\n");
        goto ERROR_POINT;

    }

    /* Update default route configuration in JSON object */
    cJSON_ReplaceItemInObject(config, "default", cJSON_CreateString(dev));

    /* Convert updated JSON object to string representation */
    CONFIG_WRITE = cJSON_Print(config);
    
    /* Write updated configuration back to file system */
    if (write_file(CONFIG_APN, CONFIG_WRITE) < 0)
    {
        printf("ERROR: wwan_route_defaultSet error!\n");
        goto ERROR_POINT;
    }

    /* Set success status and display confirmation message */
    ret = TRUE;
    printf("route default %s\n", dev);

ERROR_POINT:
    /* Clean up JSON object and allocated memory */
    cJSON_Delete(config);
    if (CONFIG_WRITE != NULL)
    {
        free(CONFIG_WRITE);
        CONFIG_WRITE = NULL;
    }

    return ret;
}

/**
 * @brief Validate if route configuration already exists for specified device
 * This function checks if the provided IP and mask combination already exists
 * in the route configuration for the specified network device to prevent duplicates
 * @param dev: Network device name to check for existing route configuration
 * @param ip: IP address to validate against existing routes
 * @param mask: Subnet mask to validate against existing routes
 * @return uint8_t Returns TRUE if route is valid and doesn't exist, FALSE if duplicate found
 */
static uint8_t is_route_valid(char *dev, char *ip, char *mask)
{
    /* Static buffer for JSON configuration content */
    static uint8_t CONFIG_STRING[JSON_LEN] = {0};
    
    /* JSON object pointer for configuration parsing */
    cJSON *config;
    
    /* JSON object pointers for device and route configuration */
    cJSON *device_item = NULL;
    cJSON *route_ip_item = NULL;
    cJSON *route_mask_item = NULL;

    /* Variable to store number of existing routes */
    uint8_t route_num = 0;

    /* String buffer for JSON configuration output */
    char *CONFIG_WRITE = NULL;

    /* Initialize configuration buffer with null characters */
    memset(CONFIG_STRING, 0x00, JSON_LEN);
    
    /* Retrieve current configuration from JSON file */
    if (!getConfig(CONFIG_STRING, CONFIG_APN))
    {
        printf("ERROR: route valid check file getConfig CONFIG_APN failed!\n");
        return FALSE;
    }

    /* Parse JSON configuration string into cJSON object structure */
    config = string2Json(CONFIG_STRING);
    
    /* Validate all input parameters are not NULL */
    if ((dev == NULL) || (ip == NULL) || (mask == NULL))
    {
        printf("ERROR: route valid check file parm null failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Verify that specified device type is supported by system */
    if (!is_dev_type_valid(dev))
    {
        printf("ERROR: route valid check file dev type error failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Retrieve device-specific configuration from main JSON object */
    device_item = cJSON_GetObjectItem(config, dev);
    if (device_item == NULL)
    {
        printf("ERROR: route valid check file device_item in config null failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Extract route IP array from device configuration */
    route_ip_item = cJSON_GetObjectItem(device_item, "route_ip");
    if ((route_ip_item == NULL) || (route_ip_item->type != cJSON_Array))
    {
        printf("ERROR: route valid check file route_ip get failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Determine number of existing routes for validation */
    route_num = (uint8_t)cJSON_GetArraySize(route_ip_item);
    
    /* Validate that route count doesn't exceed system limits */
    if (!is_route_num_valid(route_num))
    {
        printf("ERROR: route valid check file The number of routes exceeds 10\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Extract route mask array from device configuration */
    route_mask_item = cJSON_GetObjectItem(device_item, "route_netmask");
    if ((route_mask_item == NULL) || (route_mask_item->type != cJSON_Array))
    {
        printf("ERROR: route valid check file route_netmask failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /**Check if the IP and mask combination already exists in configuration**/
    for (uint8_t i = 0; i < route_num; i++)
    {
        /* Compare both IP address and subnet mask against existing entries */
        if (!strcmp(ip, (char *)(cJSON_GetArrayItem(route_ip_item, i)->valuestring)) &&
            !strcmp(mask, (char *)(cJSON_GetArrayItem(route_mask_item, i)->valuestring)))
        {
            cJSON_Delete(config);
            printf("ERROR: route valid check already existed!\n");
            // Route already exists in configuration
            return FALSE;
        }
    }

    cJSON_Delete(config);
    return TRUE;
}

/**
 * @brief Validate if network device type is supported by system
 * This function checks if the specified device name matches supported
 * network interface types (ppp0, ppp1, eth1) with conditional compilation
 * @param dev: Network device name to validate against supported types
 * @return uint8_t Returns 1 if device type valid, 0 if unsupported type
 */
uint8_t is_dev_type_valid(char *dev){

#ifdef NOT_CHECK_ETH1
   return 1;
#else
   return !(strcmp(dev, "ppp0") && strcmp(dev, "ppp1") && strcmp(dev, "eth1"));
#endif 

}

/**
 * @brief Clear all route configurations for specified network device
 * This function removes all route entries associated with the specified
 * network device from the persistent JSON configuration file
 * @param dev: Network device name to clear all route configurations for
 * @return uint8_t Returns TRUE if routes cleared successfully, FALSE on error
 */
uint8_t clear_routeMsg(char *dev)
{
    /* Static buffer for JSON configuration content */
    static uint8_t CONFIG_STRING[JSON_LEN] = {0};
    
    /* JSON object pointer for configuration manipulation */
    cJSON *config;
    
    /* JSON object pointers for device and route configuration */
    cJSON *device_item = NULL;
    cJSON *route_ip_item = NULL;
    cJSON *route_mask_item = NULL;

    /* Variable to store number of existing routes */
    uint8_t route_num = 0;

    /* String buffer for JSON configuration output */
    char *CONFIG_WRITE = NULL;

    /* Initialize configuration buffer with null characters */
    memset(CONFIG_STRING, 0x00, JSON_LEN);
    
    /* Retrieve current configuration from JSON file */
    if (!getConfig(CONFIG_STRING, CONFIG_APN))
    {
        printf("ERROR: clear route getConfig CONFIG_APN failed!\n");
        return FALSE;
    }

    /* Parse JSON configuration string into cJSON object structure */
    config = string2Json(CONFIG_STRING);
    
    /* Validate input parameter is not NULL */
    if ((dev == NULL) )
    {
        printf("ERROR: clear route parm null failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Verify that specified device type is supported by system */
    if (!is_dev_type_valid(dev))
    {
        printf("ERROR: clear route dev type error failed! %s\n",dev);
        cJSON_Delete(config);
        return FALSE;
    }

    /* Retrieve device-specific configuration from main JSON object */
    device_item = cJSON_GetObjectItem(config, dev);
    if (device_item == NULL)
    {
        printf("ERROR: clear route device_item in config null failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Extract route IP array from device configuration */
    route_ip_item = cJSON_GetObjectItem(device_item, "route_ip");
    if ((route_ip_item == NULL) || (route_ip_item->type != cJSON_Array))
    {
        printf("ERROR: clear route route_ip get failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Determine number of existing routes for processing */
    route_num = (uint8_t)cJSON_GetArraySize(route_ip_item);
    
    /* Validate that route count doesn't exceed system limits */
    if (!is_route_num_valid(route_num))
    {
        printf("ERROR: clear route The number of routes exceeds 10\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Extract route mask array from device configuration */
    route_mask_item = cJSON_GetObjectItem(device_item, "route_netmask");
    if ((route_mask_item == NULL) || (route_mask_item->type != cJSON_Array))
    {
        printf("ERROR: clear route route_netmask failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }
    
    int found_idx = -1;
    
    /**Remove all route entries from IP and mask arrays**/
    for (uint8_t i = 0; i < route_num; i++)
    {
        /* Delete route IP entry from JSON array */
        cJSON_DeleteItemFromArray(route_ip_item, i);
        
        /* Delete corresponding route mask entry from JSON array */
        cJSON_DeleteItemFromArray(route_mask_item, i);
    }

    /* Convert updated JSON object to string representation */
    CONFIG_WRITE = cJSON_Print(config);

    /* Write updated configuration back to file system */
    if (write_file(CONFIG_APN, CONFIG_WRITE) < 0)
    {
        cJSON_Delete(config);
        if (CONFIG_WRITE != NULL)
        {
            free(CONFIG_WRITE);
            CONFIG_WRITE = NULL;
        }

        printf("ERROR: clear route write_file failed!\n");
        return FALSE;
    }

    /* Clean up JSON object and allocated memory */
    cJSON_Delete(config);
    if (CONFIG_WRITE != NULL)
    {
        free(CONFIG_WRITE);
        CONFIG_WRITE = NULL;
    }

    return TRUE;
    
}

/**
 * @brief Save route configuration to persistent JSON configuration file
 * This function adds or updates route entries in the configuration file
 * for the specified network device with proper duplicate checking
 * @param dev: Network device name to save route configuration for
 * @param ip: IP address of the route to be saved
 * @param mask: Subnet mask of the route to be saved
 * @return uint8_t Returns TRUE if route saved successfully, FALSE on error
 */
uint8_t save_routeMsg(char *dev, char *ip, char *mask)
{
    /* Static buffer for JSON configuration content */
    static uint8_t CONFIG_STRING[JSON_LEN] = {0};
    
    /* JSON object pointer for configuration manipulation */
    cJSON *config;
    
    /* JSON object pointers for device and route configuration */
    cJSON *device_item = NULL;
    cJSON *route_ip_item = NULL;
    cJSON *route_mask_item = NULL;

    /* Variable to store number of existing routes */
    uint8_t route_num = 0;

    /* String buffer for JSON configuration output */
    char *CONFIG_WRITE = NULL;

    /* Initialize configuration buffer with null characters */
    memset(CONFIG_STRING, 0x00, JSON_LEN);
    
    /* Retrieve current configuration from JSON file */
    if (!getConfig(CONFIG_STRING, CONFIG_APN))
    {
        printf("ERROR: save to config file getConfig CONFIG_APN failed!\n");
        return FALSE;
    }

    /* Parse JSON configuration string into cJSON object structure */
    config = string2Json(CONFIG_STRING);
    
    /* Validate all input parameters are not NULL */
    if ((dev == NULL) || (ip == NULL) || (mask == NULL))
    {
        printf("ERROR: save to config file parm null failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Verify that specified device type is supported by system */
    if (!is_dev_type_valid(dev))
    {
        printf("ERROR: save to config file dev type error failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Retrieve device-specific configuration from main JSON object */
    device_item = cJSON_GetObjectItem(config, dev);
    if (device_item == NULL)
    {
        printf("ERROR: save to config file device_item in config null failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Extract route IP array from device configuration */
    route_ip_item = cJSON_GetObjectItem(device_item, "route_ip");
    if ((route_ip_item == NULL) || (route_ip_item->type != cJSON_Array))
    {
        printf("ERROR: save to config file route_ip get failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Determine number of existing routes for validation */
    route_num = (uint8_t)cJSON_GetArraySize(route_ip_item);
    
    /* Validate that route count doesn't exceed system limits */
    if (!is_route_num_valid(route_num))
    {
        printf("ERROR: save to config file The number of routes exceeds 10\n");
        cJSON_Delete(config);
        return FALSE;
    }

    /* Extract route mask array from device configuration */
    route_mask_item = cJSON_GetObjectItem(device_item, "route_netmask");
    if ((route_mask_item == NULL) || (route_mask_item->type != cJSON_Array))
    {
        printf("ERROR: save to config file route_netmask failed!\n");
        cJSON_Delete(config);
        return FALSE;
    }
    
    int found_idx = -1;
    
    /**Check if route already exists and find its index**/
    for (uint8_t i = 0; i < route_num; i++)
    {
        /* Compare both IP address and subnet mask against existing entries */
        if (!strcmp(ip, (char *)(cJSON_GetArrayItem(route_ip_item, i)->valuestring)) &&
            !strcmp(mask, (char *)(cJSON_GetArrayItem(route_mask_item, i)->valuestring)))
        {
            // cJSON_Delete(config);
            // // already existed
            // return TRUE;
            found_idx = i;
        }
    }
    
    /* Remove existing route entry if duplicate found */
    if (found_idx != -1){
        /* Delete existing route IP entry from JSON array */
        cJSON_DeleteItemFromArray(route_ip_item, found_idx);
        
        /* Delete existing route mask entry from JSON array */
        cJSON_DeleteItemFromArray(route_mask_item, found_idx);
    }

    /* Add new route configuration to JSON arrays */
    cJSON_AddItemReferenceToArray(route_ip_item, cJSON_CreateString(ip));
    cJSON_AddItemReferenceToArray(route_mask_item, cJSON_CreateString(mask));

    /* Convert updated JSON object to string representation */
    CONFIG_WRITE = cJSON_Print(config);

    /* Write updated configuration back to file system */
    if (write_file(CONFIG_APN, CONFIG_WRITE) < 0)
    {
        cJSON_Delete(config);
        if (CONFIG_WRITE != NULL)
        {
            free(CONFIG_WRITE);
            CONFIG_WRITE = NULL;
        }

        printf("ERROR: save to config file write_file failed!\n");
        return FALSE;
    }

    /* Clean up JSON object and allocated memory */
    cJSON_Delete(config);
    if (CONFIG_WRITE != NULL)
    {
        free(CONFIG_WRITE);
        CONFIG_WRITE = NULL;
    }

    return TRUE;
}

/**
 * @brief Validate IP address format and content
 * This function performs comprehensive validation of IP address string
 * including format checking, octet range validation, and structure verification
 * @param ip: IP address string to validate for proper format and values
 * @return uint8_t Returns TRUE if IP address is valid, FALSE if invalid format
 */
static uint8_t ip_check(char *ip)
{
    /* Calculate length of IP address string for validation */
    uint8_t ip_len = strlen(ip);
    
    /* Temporary buffer for IP address processing */
    char ip_temp[15] = {0};
    
    /* Counter for number of dot separators in IP address */
    uint8_t dopt_num = 0;

    /* Variables to store individual IP address octets as integers */
    int ip_1 = 0;
    int ip_2 = 0;
    int ip_3 = 0;
    int ip_4 = 0;

    /* String buffers for individual IP address octets */
    char ip_a[3] = {0};
    char ip_b[3] = {0};
    char ip_c[3] = {0};
    char ip_d[3] = {0};

    /* Check if IP address length exceeds maximum allowed size */
    if (ip_len > 15)
    {
        return FALSE;
    }

    /* Copy IP address to temporary buffer for safe processing */
    memcpy(ip_temp, ip, 15);

    /* Count number of dot separators in IP address string */
    for (uint8_t i = 0; i < ip_len; i++)
    {
        if (ip[i] == '.')
        {
            dopt_num++;
        }
    }

    /* Validate that IP address contains exactly three dots */
    if (dopt_num != 3)
    {
        return FALSE;
    }

    /* Parse IP address into individual octets as integer values */
    sscanf(ip_temp, "%d.%d.%d.%d", &ip_1, &ip_2, &ip_3, &ip_4);
    
    /* Validate that all octets are within valid range (0-255) */
    if (ip_1 > 255 || ip_2 > 255 || ip_3 > 255 || ip_4 > 255)
    {
        return FALSE;
    }

    /* Parse IP address into individual octets as string values */
    sscanf(ip_temp, "%[^.].%[^.].%[^.].%[^.]", ip_a, ip_b, ip_c, ip_d);
    
    /* Validate that all octets have non-zero length */
    if (!strlen(ip_a) || !strlen(ip_b) || !strlen(ip_c) || !strlen(ip_d))
    {
        return FALSE;
    }

    return TRUE;
}

/**
 * @brief Add new route to specified network device
 * This comprehensive function validates input parameters, adds route to system
 * routing table, and synchronizes configuration with persistent storage
 * @param dev: Network device name to add route to
 * @param ip: IP address of the route destination network
 * @param mask: Subnet mask for the route destination network
 * @return uint8_t Returns TRUE if route added successfully, FALSE on any error
 */
uint8_t wwan_route_add(char *dev, char *ip, char *mask)
{
    /* Buffer for system command execution */
    char cmd[256] = {0};

    /* Validate that IP and mask contain only valid characters (digits and dots) */
    if ((strspn(ip, "0123456789.") != strlen(ip)) || (strspn(mask, "0123456789.") != strlen(mask)))
    {
        printf("ERROR: Illegal input.\n");
        return FALSE;
    }

    /* Validate IP address format and content */
    if (!ip_check(ip))
    {
        printf("ERROR: IP illegal.\n");
        return FALSE;
    }

    /* Validate subnet mask format and content */
    if (!ip_check(mask))
    {
        printf("ERROR: MASK illegal.\n");
        return FALSE;
    }

    // Commented out duplicate route checking - available for future use

    // if (is_route_valid(dev, ip, mask))
    // {
    //     printf("ERROR: route add check failed.\n");
    //     return FALSE;
    // }
    // Add a route
    if (add_route(dev, ip, mask)){
        //printf("add_route successfully.\n");
    } else {
        printf("Failed add_route.\n");
        return FALSE;
    }

    RouteTable table = {0};
    if (wwan_route_sync(&table)) {
        //printf("Routes saved successfully.\n");
    } else {
        printf("Failed to save routes to config file.\n");
        return FALSE;
    }

    printf("route add ip %s\nroute add netmask %s\n", ip, mask);

    return TRUE;
}

/**
 * @brief wwan_route_delete
 *
 * @param dev
 * @param num
 * @return uint8_t
 */
uint8_t wwan_route_delete(char *dev, char *num)
{
    static uint8_t CONFIG_STRING[JSON_LEN] = {0};
    char cmd[500] = {0};
    char route_ip_string[128] = {0};
    char route_ip_mask[128] = {0};
    cJSON *config;

    cJSON *device_item = NULL;
    cJSON *route_ip_item = NULL;
    cJSON *route_mask_item = NULL;
    cJSON *route_ip = NULL;
    cJSON *route_mask = NULL;
    uint8_t ret = FALSE;

    char *CONFIG_WRITE = NULL;

    int index = atoi(num) - 1;

    memset(CONFIG_STRING, 0x00, JSON_LEN);
    if (!getConfig(CONFIG_STRING, CONFIG_APN))
    {
        printf("ERROR: wwan_route_delete getConfig CONFIG_APN error!\n");
        return FALSE;
    }

    config = string2Json(CONFIG_STRING);
    if (dev == NULL)
    {
        printf("dev is NULL\n");
        return FALSE;
    }

    if (!is_dev_type_valid(dev))
    {
        printf("ERROR: wwan_route_delete dev type  error!\n");
        return FALSE;
    }

    device_item = cJSON_GetObjectItem(config, dev);
    if (device_item == NULL)
    {
        printf("ERROR: wwan_route_delete device_item in config null error!\n");
        return FALSE;
    }

    route_ip_item = cJSON_GetObjectItem(device_item, "route_ip");
    if (route_ip_item == NULL)
    {
        printf("ERROR: wwan_route_delete route_ip get error!\n");
        return FALSE;
    }

    route_mask_item = cJSON_GetObjectItem(device_item, "route_netmask");
    if (route_mask_item == NULL)
    {
        printf("ERROR: wwan_route_delete route_netmask error!\n");
        return FALSE;
    }

    route_ip = cJSON_GetArrayItem(route_ip_item, index);
    if (route_ip != NULL && route_ip->valuestring != NULL) {
        strcpy(route_ip_string, route_ip->valuestring);
    } else {
        printf("ERROR: wwan_route_delete route_ip error!\n");
        return FALSE;
    }

    route_mask = cJSON_GetArrayItem(route_mask_item, index);
    if (route_mask != NULL && route_mask->valuestring != NULL) {
        strcpy(route_ip_mask, route_mask->valuestring);
    } else {
        printf("ERROR: wwan_route_delete route_mask error!\n");
        return FALSE;
    }

    // 调用系统命令删除路由
    if (del_route(dev, route_ip_string, route_ip_mask)) {
        printf("Delete command executed successfully.\n");
    } else {
        goto DELETE_ERROR;
    }
    
    RouteTable table = {0};
    if (wwan_route_sync(&table)) {
        //printf("Routes saved successfully.\n");
    } else {
        printf("Failed to save routes to config file.\n");
        return FALSE;
    }

    ret = TRUE;
    printf("route %s %d delete success\n", dev, atoi(num));

DELETE_ERROR:
    cJSON_Delete(config);

    if (CONFIG_WRITE != NULL)
    {
        free(CONFIG_WRITE);
        CONFIG_WRITE = NULL;
    }



    return ret;
}

/**
 * @brief log_setting
 *
 * @param enable
 * @return uint8_t
 */
static uint8_t log_setting(uint8_t enable)
{
    static uint8_t CONFIG_STRING[JSON_LEN] = {0};
    cJSON *config = NULL;
    char *CONFIG_WRITE = NULL;

    memset(CONFIG_STRING, 0x00, JSON_LEN);
    if (!getConfig(CONFIG_STRING, CONFIG_APN))
    {
        printf("ERROR: getConfig failed!\n");
        return FALSE;
    }

    config = string2Json(CONFIG_STRING);
    if (config == NULL)
    {
        return FALSE;
    }

    if (enable)
    {
        cJSON_ReplaceItemInObject(config, "log", cJSON_CreateString("yes"));
    }
    else
    {
        cJSON_ReplaceItemInObject(config, "log", cJSON_CreateString("no"));
    }

    CONFIG_WRITE = cJSON_Print(config);
    if (CONFIG_WRITE == NULL)
    {
        cJSON_Delete(config);
        return FALSE;
    }
    if (write_file(CONFIG_APN, CONFIG_WRITE) < 0)
    {
        printf("ERROR: write_file error!\n");
        cJSON_Delete(config);
        if (CONFIG_WRITE != NULL)
        {
            free(CONFIG_WRITE);
            CONFIG_WRITE = NULL;
        }
        return FALSE;
    }

    cJSON_Delete(config);
    if (CONFIG_WRITE != NULL)
    {
        free(CONFIG_WRITE);
        CONFIG_WRITE = NULL;
    }
    return TRUE;
}

/**
 * @brief wwwan_log_start
 *
 * @return uint8_t
 */
uint8_t wwwan_log_start(void)
{
    if (!log_setting(SET))
    {

        printf("ERROR: wwwan_log_start error!\n");
        return FALSE;
    }

    log_manageInit();

    printf("log start success!!\n");

    return TRUE;
}

/**
 * @brief wwwan_log_stop
 *
 * @return uint8_t
 */
uint8_t wwwan_log_stop(void)
{
    if (!log_setting(RESET))
    {
        printf("ERROR: wwwan_log_stop error!\n");
        return FALSE;
    }

    log_closeFile();

    printf("log stop success!!\n");

    return TRUE;
}

/**
 * @brief wwan_at_send
 *
 * @param command
 * @param dev
 * @return uint8_t
 */
uint8_t wwan_at_send(char *command, char *dev)
{
    char cmd_buf[APN_NAME_LEN] = {0};
    uint8_t uart_buffer[APN_NAME_LEN] = {0};

    uint8_t rec_num = 0;
    char port_dev[32] = {0};
    memset(port_dev, 0, sizeof(port_dev));

    //判断是否存在对应的网络节点dev
    if (dev_network_node_fine(dev))
    {
        //通过配置.json文件获取对应的设备节点
        if(!get_json_dev_keyvalue(port_dev,dev))
        {
            printf("ERROR: get_dev_node failed!\n");
            return FALSE;
        }
    }
    else
    {
        printf("ERROR: wwan_at_send failed!\n");
        return FALSE;
    }

    if (!uart_init(port_dev, 115200, 8, 'N', 1))
    {
        printf("ERROR: wwan_at_send failed!\n");
        return FALSE;
    }

    sprintf(cmd_buf, "%s\r", command);

    if (serial_send((uint8_t *)cmd_buf, strlen(cmd_buf)) > 0)
    {
        delay_ms(300);

        do
        {
            rec_num = serial_recv(uart_buffer + rec_num, APN_NAME_LEN);

        } while (rec_num);

        log_printf(MSG_INFO, "%s\n%s\n", command, uart_buffer);
        
        printf("%s", command);
        printf("%s", uart_buffer);
    }

    if (!uart_destory())
    {
        printf("ERROR: wwan_at_send failed!\n");
        return FALSE;
    }

    return TRUE;
}

/**
 * @brief wwwan_log_show
 *
 * @return uint8_t
 */
uint8_t wwwan_log_show(void)
{
    // static uint8_t CONFIG_STRING[JSON_LEN] = {0};

    // memset(CONFIG_STRING, 0x00, JSON_LEN);

    // if (!getConfig(CONFIG_STRING, LOG_PATH))
    // {
    //     printf("ERROR: wwwan_log_show failed!\n");
    //     return FALSE;
    // }

    // printf("%s\n", CONFIG_STRING);

    return TRUE;
}

uint8_t dev_network_node_fine(const char *dev) 
{
    FILE *fp;
    char path[1035];
    char command[50];
    int found = 0;

    // 构建ifconfig命令
    snprintf(command, sizeof(command), "ifconfig %s 2>&1", dev);

    // 执行命令并打开管道
    fp = popen(command, "r");
    if (fp == NULL) {
        return 0; // 如果无法打开管道，返回0
    }

    // 读取命令输出
    while (fgets(path, sizeof(path), fp) != NULL) {
        // 检查输出中是否包含"Device not found"
        if (strstr(path, "Device not found") != NULL) {
            found = 0; // 设备不存在
            break;
        } else {
            found = 1; // 设备存在
        }
    }

    // 关闭管道
    pclose(fp);
    return found; // 返回设备存在与否
}

uint8_t get_json_dev_keyvalue(char *keyvalue,const char *dev_node)
{
    uint8_t CONFIG_STRING[JSON_LEN] = {0};
    cJSON *config = NULL;
	cJSON *log_status;
    char node_name[32] = {0};

    memset(CONFIG_STRING, 0x00, JSON_LEN);
    memset(node_name, 0x00, sizeof(node_name));

    if (!getConfig(CONFIG_STRING, CONFIG_APN))
    {
        printf("ERROR: getConfig failed!\n");
        return FALSE;
    }

    config = string2Json(CONFIG_STRING);
    if (config == NULL)
    {
        return FALSE;
    }

    sprintf(node_name,"%s-dev",dev_node);

    log_status = cJSON_GetObjectItem(config, node_name);
    if (log_status == NULL)
    {
        cJSON_Delete(config);
        return FALSE;
    }
    else
    {
        if (log_status->type != cJSON_String)
        {	
            cJSON_Delete(config);
            return FALSE;
        }
    }

    memcpy(keyvalue, log_status->valuestring, strlen(log_status->valuestring));
    //printf("node:%s\n",keyvalue);

    cJSON_Delete(config);
    return TRUE;
}